/*
 * @Date: 2022-02-23 10:34:46
 * @LastEditors: 春贰
 * @gitee: https://gitee.com/chun22222222
 * @github: https://github.com/chun222
 * @Desc:
 * @LastEditTime: 2023-11-28 10:28:13
 * @FilePath: \server\system\service\BaseService\login.go
 */
package BaseService

import (
	"fmt"
	"time"

	"go-easy-dashboard/system/core/cache"
	"go-easy-dashboard/system/core/db"
	"go-easy-dashboard/system/core/request"
	"go-easy-dashboard/system/model/DbModel"
	"go-easy-dashboard/system/model/RequestModel"
	"go-easy-dashboard/system/util/jwtUtil"
	"go-easy-dashboard/system/util/sys"
	"gorm.io/gorm"
)

type LoginService struct{}

func (loginService *LoginService) Login(info RequestModel.Login) (error, *DbModel.SysUser) {

	err, data := func() (error, *DbModel.SysUser) {

		errReturn := &DbModel.SysUser{
			UserName:  info.Loginname,
			LoginName: info.Loginname,
			Ip:        info.Ip,
		}
		err, user := loginService.ValUserPass(info.Loginname, info.Password, false)

		if err != nil {
			return err, errReturn
		}

		//缓存
		cache.Set(user.LoginName, user.Permissions, -1)

		//返回时删除某些字段
		user.Photo = ""
		user.RecognitionCode = ""

		//创建token
		j := jwtUtil.NewJWT()
		claims := j.CreateClaims(jwtUtil.BaseClaims{
			LoginName: user.LoginName,
			UserName:  user.UserName,
			Ip:        info.Ip,
		})
		token, _ := j.CreateToken(claims)
		user.Token = token
		user.Ip = claims.Ip

		return nil, user

	}()

	//记录日志
	var loginWay uint = info.LoginType
	if info.Photo != "" {
		loginWay = 3
	}
	logstatus := 1
	msg := ""
	if err != nil {
		logstatus = 2
		msg = err.Error()
	}
	datalog := DbModel.SysLoginLog{
		LoginName: data.LoginName,
		UserName:  data.UserName,
		Status:    logstatus,
		Msg:       msg,
		Ip:        data.Ip,
		Login:     time.Now(),
		LoginWay:  loginWay,
	}
	go db.Instance().Model(DbModel.SysLoginLog{}).Save(&datalog)

	return err, data

}

//验证用户密码
func (loginService *LoginService) ValUserPass(LoginName string, Password string, passIsEncrypt bool) (err error, user *DbModel.SysUser) {
	EncryptPass := Password
	if !passIsEncrypt {
		EncryptPass = sys.EncryptPass(Password)
	}
	err = db.Instance().Where("login_name = ? AND password = ? and status = 1", LoginName, EncryptPass).Preload("Roles", func(db *gorm.DB) *gorm.DB {
		return db.Order("id asc")
	}).Preload("Permissions", func(db *gorm.DB) *gorm.DB {
		return db.Where("status = ?", 1).Order("sort asc")
	}).Preload("Roles.Permissions", func(db *gorm.DB) *gorm.DB {
		return db.Where("status = ?", 1).Order("sort asc")
	}).First(&user).Error

	//可能为域控
	if err != nil {
		return fmt.Errorf("用户名密码错误"), user
	}

	//判断密码是否过期
	if user.PassAvailableDays != 0 && user.PassUpdate != nil && user.PassUpdate.AddDate(0, 0, int(user.PassAvailableDays)).Before(time.Now()) {
		return fmt.Errorf("密码已经过期"), user
	}

	if len(user.Roles) > 0 {
		user.MenuRoleName = user.Roles[0].Name
	}

	user.Permissions = mergePermissions(user)
	return nil, user

}

//根据id获取权限
func (loginService *LoginService) GetPerByLoginName(login_name string) (err error, user *DbModel.SysUser) {

	err = db.Instance().Where("login_name = ?  and status = 1", login_name).Preload("Roles", func(db *gorm.DB) *gorm.DB {
		return db.Order("id asc")
	}).Preload("Permissions", func(db *gorm.DB) *gorm.DB {
		return db.Where("status = ?", 1).Order("sort asc")
	}).Preload("Roles.Permissions", func(db *gorm.DB) *gorm.DB {
		return db.Where("status = ?", 1).Order("sort asc")
	}).First(&user).Error

	if err != nil {
		return err, user
	}

	if len(user.Roles) > 0 {
		user.MenuRoleName = user.Roles[0].Name
	}

	user.Permissions = mergePermissions(user)
	//缓存
	cache.Set(user.LoginName, user.Permissions, -1)
	//返回时删除某些字段
	user.Photo = ""
	user.RecognitionCode = ""
	return err, user
}

//合并权限
func mergePermissions(u *DbModel.SysUser) []DbModel.SysPermission {
	r := make([]DbModel.SysPermission, 0)
	//fmt.Printf("%+v", u.Permissions)
	for _, v := range u.Permissions {
		r = append(r, v)
	}

	for _, _roles := range u.Roles {
		for _, v := range _roles.Permissions {
			r = append(r, v)
		}
	}

	//去重
	result := make([]DbModel.SysPermission, 0)
	temp := map[string]byte{}
	for _, value := range r {
		l := len(temp)
		temp[value.Name] = 0
		if len(temp) != l {
			result = append(result, value)
		}
	}
	return result

}

func (loginService *LoginService) LoginLog(info RequestModel.LoginLog) (err error, list []DbModel.SysLoginLog, total int64) {

	//登陆日志
	limit := info.PageSize
	offset := info.PageSize * (info.Page - 1)

	db := db.Instance().Model(&DbModel.SysLoginLog{})
	//动态查询条件
	request.GenWhere(info, db)

	var dataList []DbModel.SysLoginLog
	err = db.Count(&total).Error
	if err != nil {
		return
	}
	err = db.Order("create_time desc").Limit(limit).Offset(offset).Find(&dataList).Error
	return err, dataList, total

}
